#include "ImageProcessor.h"
#include "afterdetect.h"
#include "detectcachemodel.h"
#include "source/configmanager.h"
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDir>
#include "errordialogmanager.h"
#include "faultcachemodel.h"

AfterDetect& AfterDetect::getInstance() {
    static AfterDetect instance;
    return instance;
}


int AfterDetect::addImageId()
{
    imageCardId++;
    qInfo() << "imageCardId:" << imageCardId;
    return imageCardId;
}

void AfterDetect::inPlaceadjustCacheremove34(int currentIndex, int offset)
{
    for (int i = currentIndex; i < offset; i++) {
        int moveIndex = currentIndex + i;

        // 检查 moveIndex 是否存在并且 ID 大于 0
        if (Cache_.contains(moveIndex) && moveIndex > 0) {
            std::vector<int>& defectList = Cache_[moveIndex];  // 获取对应的 vector<int>

            // 移除 defectList 中的 36
            auto new_end = std::remove(defectList.begin(), defectList.end(), 34);
            if (new_end != defectList.end()) {
                defectList.erase(new_end, defectList.end());  // 删除 36 后的元素
            }
        }
    }
}


void AfterDetect::inPlaceadjustCache( int currentIndex, int offset) {
    // 检查 currentIndex 是否在 Cache_ 中，不在则直接返回
    // 如果 currentIndex 不在 Cache_ 中，直接返回
    //if (!Cache_.contains(currentIndex)) return;
    ErrorDialogManager::instance().showNonBlockingInfo("出现错位或者位移", "系统自动补位一个");
    // 逐一移动 `currentIndex` 前的 `offset` 个元素
    for (int i = 1; i <= offset; i++) {
        int moveIndex = currentIndex - i;
        // 检查 moveIndex 是否存在并且 ID 大于 0
        if (Cache_.contains(moveIndex) && moveIndex > 0) {
            // 将 moveIndex 的元素移动到 moveIndex + 1 位置
            Cache_[moveIndex + 1] = Cache_[moveIndex];
        }
    }

    // 在 currentIndex 位置插入 [13]，覆盖原有元素
    Cache_[currentIndex-offset] = {28};
}

bool AfterDetect::getCacheWasteAnd24(int index) {
    // 检查 Cache_ 是否包含该键
    if (Cache_.contains(index)) {
        // 获取对应的 std::vector<int>
        std::vector<int> vec = Cache_.value(index);

        // 移除值为 26 和 24 的元素
        vec.erase(std::remove(vec.begin(), vec.end(), 26), vec.end());
        vec.erase(std::remove(vec.begin(), vec.end(), 24), vec.end());

        // 如果移除后为空，则返回 true
        return vec.empty();
    }

    // 如果 Cache_ 不包含该键，返回 false
    return true;
}

bool AfterDetect::getCacheWaste(int index) {
    // 检查 Cache_ 是否包含该键
    if (Cache_.contains(index)) {
        // 获取对应的 std::vector<int>
        const std::vector<int>& vec = Cache_.value(index);

        // 检查 std::vector<int> 是否为空或仅包含一个元素 26
        if (!vec.empty() && !(vec.size() == 1 && vec[0] == 26)) {
            return true;
        }
    }

    // 返回 false 如果为空或者仅包含 26
    return false;
}

bool AfterDetect::containsDefect(int index, int defect) {
    // 检查 Cache_ 是否包含该键
    if (Cache_.contains(index)) {
        // 获取对应的 std::vector<int>
        const std::vector<int>& vec = Cache_.value(index);
        // 检查 std::vector<int> 是否包含 defect
        if (std::find(vec.begin(), vec.end(), defect) != vec.end()) {
            return true;
        }
    }
    return false;
}

void AfterDetect::addCacheDetect(int id, int defect) {
    if (Cache_.contains(id)) {
        // 获取对应的 std::vector<int>
        std::vector<int>& vec = Cache_[id]; // 使用引用以便直接修改

        // 检查是否已经存在该缺陷，避免重复添加
        if (std::find(vec.begin(), vec.end(), defect) == vec.end()) {
            vec.push_back(defect);

            // 如果需要对新增缺陷排序
            std::sort(vec.begin(), vec.end());

            DetectCacheModel::instance().updateDefectById(id, vec);
            qInfo() << "Added defect" << defect << "to cache with id" << id;
        } else {
            qInfo() << "Defect" << defect << "already exists in cache with id" << id;
        }
    } else {
        // 如果 id 不存在，创建新的 entry
        Cache_[id] = {defect};
        DetectCacheModel::instance().updateDefectById(id, {defect});
        qInfo() << "Created new cache entry and added defect" << defect << "for id" << id;
    }
}


void AfterDetect::removeCacheDetect(int id, int defect) {
    if (Cache_.contains(id)) {
        // 获取对应的 std::vector<int>
        std::vector<int>& vec = Cache_[id]; // 使用引用以便直接修改
        // 使用 std::remove 移动要删除的元素到末尾，然后调用 erase 删除
        vec.erase(std::remove(vec.begin(), vec.end(), defect), vec.end());

        DetectCacheModel::instance().updateDefectById(id, vec);
        // 如果需要，可以在这里添加日志或其他操作
        qInfo() << "Removed defect" << defect << "from cache with id" << id;
    } else {
        qWarning() << "No cache found for id" << id;
    }
}


int AfterDetect::getImageId()
{
    return imageCardId;
}

AfterDetect::AfterDetect(QObject *parent) : QObject(parent), totailId(0) {
    this->moveToThread(&threadAfterDetect);
    threadAfterDetect.start();

    connect(this, &AfterDetect::addDataItem, &DetectCacheModel::instance(),
            &DetectCacheModel::addDataItem);
    connect(this, &AfterDetect::addDataItem, &FaultCacheModel::instance(),
            &FaultCacheModel::addDataItem);

    connect(&DetectCacheModel::instance(),
            &DetectCacheModel::clearDetectCache,this, &AfterDetect::clearCache);
    // connect(&DetectCacheModel::instance(),
    //         &DetectCacheModel::finishAddDetectCache,
    //         this, &AfterDetect::finishAddDetectCacheSlot);
    connect(&ConfigManager::getInstance(), &ConfigManager::valueTableLoad,
            this, &AfterDetect::valueTableLoad);

    //connect(this, &AfterDetect::finished, &threadAfterDetect, &QThread::quit);
    connect(&threadAfterDetect, &QThread::finished, this, &QObject::deleteLater);
    connect(&ConfigManager::getInstance(),&ConfigManager::fileNameChanged,this,&AfterDetect::fileNameChangedSlot);
    configFileName = ConfigManager::getInstance().ccnfigfileName();
    if (!configFileName.isEmpty()) {
        initDirectory();
        if (loadCacheFromFile()) {
            LogDebug << "Loaded cache successfully from " << configFileName;
        } else {
            LogError << "Failed to load cache from " << configFileName;
        }
    }
}



void AfterDetect::valueTableLoad()
{
    //文件名变化时触发
}
void AfterDetect::defectComp(int currentID)
{
    int validCount = 0;
    int totalCount = 0;
    int continuousComp = ImageProcessor::getInstance().get_continuousComp();
    if(continuousComp != 0)
    {
        if(getCacheWaste(currentID-3) == false)
        {
            //qInfo() << "defectComp start " << currentID - 3;
            for (int offset =-6; offset <= 0; ++offset) {
                if (offset == -3) continue; // 跳过当前项

                int checkID = currentID + offset;
                // 检查当前项是否为空或仅包含 26/24
                if (getCacheWasteAnd24(checkID) == false) {
                    ++validCount;
                }
                ++totalCount;
            }
            //qInfo() << "defectComp end";
        }

        if (totalCount > 0 && (static_cast<double>(validCount) / totalCount) > 1 - 0.2f * continuousComp)
        {
            qDebug() << "defectComp for ID:" << (currentID - 3);

            addCacheDetect(currentID - 3 , 24);
        }
    }
}

void AfterDetect::getFinishProcess(ImageRecord imgCard)
{
    // if (imgCard.getState() == ImageRecord::State::Succeed)
    // {
    LogDebug << "AfterDetect::getFinishProcess selectedStep:" << ImageProcessor::getInstance().selectedStep()
    <<"displayHistory_:"<< ImageProcessor::getInstance().displayHistory_;
    ImageProcessor::MeauName currentMeau =  ImageProcessor::getInstance().selectedStep();
    if ( currentMeau == ImageProcessor::MeauDetect || currentMeau == ImageProcessor::MeauAutoDetect)
    {
        if(currentMeau == ImageProcessor::MeauAutoDetect)
        {
            qDebug() << "AutoDetect Finish ID:" << imgCard.getID();
            std::vector<int> defectItem = imgCard.getNgCard().getDefects();

            int currentID = imgCard.getID();
            Cache_[currentID] = defectItem;

            defectComp(currentID);

            appendToTotalCache(defectItem);

            ImageProcessor::getInstance().updatetodayAllnum(ImageProcessor::getInstance().todayAllnum() +1);
            emit moveDistanceSign(imgCard.moveSpace);
            emit addDataItem(imgCard);
        }
        if (ImageProcessor::getInstance().displayHistory_ == false)
        {
            cv::Mat img = imgCard.getResultImage();
            ImageProcessor::getInstance().displayOKNGReson(imgCard.getNgCard());
            ImageProvider::getInstance().image2qml(img, "Main");
            ImageProvider::getInstance().image2qml(imgCard.getbaseImage(), "Box1");
            ImageProvider::getInstance().image2qml(imgCard.getStepImage(StepProcess::Reprogress), "Box2");
            ImageProcessor::getInstance().displaydetectStepTime(imgCard.getdetectStepTime());
            ImageProcessor::getInstance().displaydetectStepInfo(imgCard.getdetectStepInfo());
        }
    }
    else if (!imgCard.getIsSkipDisplay() && ImageProcessor::getInstance().captureImgMode() != ImageProcessor::CapPause)
    {
        cv::Mat img = imgCard.getResultImage();
        ImageProcessor::getInstance().displayDisplayDelay(imgCard.getElapsedTime());
        ImageProcessor::getInstance().sendImgInfo(img);
        LogTrack << "imgCard.getStepProcess():" << imgCard.getStepProcess();
        if (imgCard.getdisplayStep() == ImageRecord::DisplayCap)
            ImageProvider::getInstance().image2qml(img, "Main", ImageProvider::Capture);
        else if (imgCard.getdisplayStep() == ImageRecord::DisplayPre)
            ImageProvider::getInstance().image2qml(img, "Main", ImageProvider::Reprogress);
        else
            ImageProvider::getInstance().image2qml(img, "Main");
    }

    lastCard = imgCard;
}

void AfterDetect::fileNameChangedSlot()
{
    //QMutexLocker locker(&mutex_);
    LogDebug << "Attempting to AfterDetect::valueTableLoad";
    totailId = 0;
    configFileName = ConfigManager::getInstance().ccnfigfileName();
    clearCache();
    clearTotalCache();
    initDirectory();
    if (loadCacheFromFile()) {
        LogDebug << "Loaded cache successfully from " << configFileName;
    } else {
        LogDebug << "Failed to load cache from " << configFileName;
    }
}
// {
//     cv::Mat img_enpty;
//     if (ImageProcessor::getInstance().captureImgMode() != ImageProcessor::CapPause)
//         imageProvider_->image2qml(img_enpty, "Main");
// }



AfterDetect::~AfterDetect() {
    threadAfterDetect.quit();
    threadAfterDetect.wait();
}

void AfterDetect::initDirectory() {
    // 如果 out 已经关联了一个文件流，并且文件流已经打开，需要先关闭它
    if (out.device() != nullptr && out.device()->isOpen()) {
        LogWarning << "out.device() has benn open Attempting to close it" ;
        out.device()->close();
    }

    QDir dir(ConfigPath);
    if (!dir.exists()) {
        dir.mkpath(".");
    }

    QString filePath = ConfigPath + configFileName + ".json";
    fileStream.setFileName(filePath);

    // 打开文件
    if (!fileStream.open(QIODevice::ReadWrite | QIODevice::Text)) {
        LogError << "AfterDetect Failed to open file: " << filePath;
    } else {
        // 重新设置 out 的设备为新的文件流
        out.setDevice(&fileStream);
        LogInfo << "AfterDetect Successfully opened file: " << filePath;
    }
}

bool AfterDetect::loadCacheFromFile() {
    if (!fileStream.isOpen()) {
        LogDebug << "Fail to loadCacheFromFile !fileStream.isOpen())" ;
        return false;
    }

    QByteArray data = fileStream.readAll();
    //LogDebug << "File content: " << data.toStdString();
    LogDebug << "AfterDetect  get data: " << data.size();

    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(data, &parseError);

    int maxId = 0;
    fileStream.seek(0);
    QTextStream in(&fileStream);
    while (!in.atEnd()) {
        QString line = in.readLine();
        QJsonDocument doc = QJsonDocument::fromJson(line.toUtf8(), &parseError);
        if (doc.isNull() || !doc.isObject()) {
            LogDebug << "JSON parse error in line: " << parseError.errorString();
            continue; // 跳过错误行
        }
        QJsonObject obj = doc.object();
        int id = obj["id"].toInt();
        if (id > maxId) {
            maxId = id;
        }
        QJsonArray defectsArray = obj["defects"].toArray();
        std::vector<int> defects;
        for (const QJsonValue &defectValue : defectsArray) {
            defects.push_back(defectValue.toInt());
        }
        TotalCache_.append(defects);
    }
    totailId = maxId + 1;  // 设置 totailId 为最大 ID 的下一个值
    LogDebug << "loadCacheFromFile Succesfull Totail Index : " << totailId;
    return true;
}

void AfterDetect::finishAddDetectCacheSlot(int id, ImageRecord imgCard) {
    // QMutexLocker locker(&mutex_);
    // std::vector<int> item = imgCard.getNgCard().getDefects();
    // Cache_[id] = item;
    // appendToTotalCache(item);
}

void AfterDetect::clearCache()
{
    qWarning() << "AfterDetect::clearCache" ;
    QMutexLocker locker(&mutex_);
    Cache_.clear();
    imageCardId = 0;
}

void AfterDetect::appendToTotalCache(const std::vector<int>& item) {
    TotalCache_.append(item);
    appendCacheToFile(item);
}

void AfterDetect::appendCacheToFile(const std::vector<int> &item) {
    QJsonObject obj;
    QJsonArray defectsArray;
    for (int defect : item) {
        defectsArray.append(defect);
    }
    obj["id"] = totailId++;
    obj["defects"] = defectsArray;
    LogTrack << "appendCacheToFile" << totailId;
    QJsonDocument doc(obj);
    out << doc.toJson(QJsonDocument::Compact) << endl;
    out.flush();  // 确保数据写入文件
}

void AfterDetect::clearTotalCache() {
    QMutexLocker locker(&mutex_);
    TotalCache_.clear();
    //fileStream.resize(0);  // Clear the file content
    LogDebug << "Caches have been cleared safely.";
}

